# Copyright (c) 2010, Ryan Bourgeois <bluedragonx@gmail.com>
# All rights reserved.
#
# This software is licensed under a modified BSD license as defined in the
# provided license file at the root of this project.  You may modify and/or
# distribute in accordance with those terms.
#
# This software is provided "as is" and any express or implied warranties,
# including, but not limited to, the implied warranties of merchantability and
# fitness for a particular purpose are disclaimed.

import re

operator_re = re.compile('^(=|>=|<=|>|<)')
category_re = re.compile('/')
version_re = re.compile('-([0-9]+|scm)')
keyword_re = re.compile('(^[~*])')

class Atom:

    def __init__(self, atom):
        self.name = None
        self.operator = None
        self.category = None
        self.version = None

        tmp = version_re.split(atom, 1)
        if len(tmp) == 3:
            atom = tmp[0]
            self.version = "%s%s" % (tmp[1], tmp[2])
        tmp = operator_re.split(atom, 1)
        if len(tmp) == 3:
            atom = tmp[2]
            self.operator = tmp[1]
        tmp = category_re.split(atom, 1)
        if len(tmp) == 2:
            atom = tmp[1]
            self.category = tmp[0]
        self.name = atom

    def match(self, atom, use_category=True, use_operator=True, use_version=True):
        if not isinstance(atom, Atom):
            atom = Atom(atom)
        res = (self.name == atom.name)
        if use_category:
            res = res and self.category == atom.category
        if use_operator:
            res = res and self.operator == atom.operator
        if use_version:
            res = res and self.version == atom.version
        return res

    def __str__(self):
        atom = self.name
        if self.category is not None:
            atom = "%s/%s" % (self.category, atom)
            if self.version is not None:
                atom = "%s-%s" % (atom, self.version)
                if self.operator is None:
                    atom = "=%s" % (atom)
                else:
                    atom = "%s%s" % (self.operator, atom)
        return atom

    def __eq__(self, other):
        if isinstance(other, Atom):
            return self.name == other.name \
                and self.operator == other.operator \
                and self.category == other.category \
                and self.version == other.version
        else:
            return str(self) == str(other)

class UseFlag:

    def __init__(self, flag):
        if flag[0] == '+' or flag[0] == '-':
            self.enabled = (flag[0] != '-')
            self.name = flag[1:]
        else:
            self.enabled = True
            self.name = flag

    @property
    def operator(self):
        if self.enabled:
            return '+'
        else:
            return '-'

    def negate(self):
        self.enabled = not self.enabled

    def match(self, flag, use_enabled=True):
        if not isinstance(flag, UseFlag):
            flag = UseFlag(flag)
        res = (self.name == flag.name)
        if use_enabled:
            res = res and self.enabled == flag.enabled
        return res

    def __str__(self, require_operator=False):
        if require_operator or not self.enabled:
            return "%s%s" % (self.operator, self.name)
        else:
            return self.name

    def __eq__(self, other):
        if isinstance(other, UseFlag):
            return self.name == other.name \
                and self.enabled == other.enabled
        else:
            return str(self) == str(other)

class Keyword:

    def __init__(self, keyword):
        self.branch = ''
        self.arch = keyword
        tmp = keyword_re.split(keyword, 1)
        if len(tmp) == 3:
            self.branch = tmp[1]
            self.arch = tmp[2]

    @property
    def stable(self):
        return self.branch == ''

    @property
    def test(self):
        return self.branch == '~'

    @property
    def anybranch(self):
        return self.branch == '*'

    @property
    def anyarch(self):
        return self.arch == '*'

    def match(self, keyword, use_branch=True, use_arch=True):
        if not isinstance(keyword, Keyword):
            keyword = Keyword(keyword)
        res = True
        if use_branch:
            res = res and self.branch == keyword.branch
        if use_arch:
            res = res and self.arch == keyword.arch
        return res

    def __str__(self):
        if self.branch == '~' or self.branch == '*':
            return self.branch + self.arch
        else:
            return self.arch

    def __eq__(self, other):
        if isinstance(other, Keyword):
            return self.branch == other.branch \
                and self.arch == other.arch

